package com.hllxd.hism.star.basic.service.model.dapan;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.influxdb.dto.QueryResult;
import org.influxdb.impl.TimeUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * 微信小程序返回结果
 * @author lixiyong01
 * @date 2018-12-24 14:11
 **/
@Data
@Slf4j
public class SeriesResult {
    public String hostName;
    public List<List<Object>> pointsAmount;

    public String host;
    /** 序列点集合， List<Object>为{time,value}组合 */
    public List<List<Object>> points;
    public List<SeriesResult> seriesResults;


    public static SeriesResult build(List<List<Object>> points){
        SeriesResult thiz = new SeriesResult();
        thiz.setPoints(points);
        return thiz;
    }
    public static SeriesResult buildHost(List<List<Object>> points,String host){
        SeriesResult thiz = new SeriesResult();
        thiz.setPoints(points);
        thiz.setHost(host);
        return thiz;
    }
    public static SeriesResult buildList(List<SeriesResult> seriesResults){
        SeriesResult thiz = new SeriesResult();
        thiz.setSeriesResults(seriesResults);
        return thiz;
    }

    public static List<Object> buildEntry(List<Object> row, List<String> columns) {
        List<Object> entry = new ArrayList<>();
        for(int i=0; i< row.size(); i++){
            //字段名
            String column = columns.get(i);
            //相应字段值
            Object value = row.get(i);
            switch (column) {
                case "time":
                    entry.add(TimeUtil.fromInfluxDBTimeFormat(String.valueOf(value)));
                    break;
                case "value":
                    entry.add(String.valueOf(value));
                    break;
                default:
                    log.error("cell column is invalid.[{}]", column);
                    break;
            }
        }
        return entry;
    }
    public static SeriesResult buildEntryList(List<QueryResult.Result> results,String host) {
        List<List<Object>> listEntry = new ArrayList<>();
        for (QueryResult.Result result : results) {
            if(result.getSeries()==null){
                log.warn("buildEntryList series is null.{}",result.getError());
                return null;
            }
            List<QueryResult.Series>  series = result.getSeries();
            for (QueryResult.Series rowsList : series) {
                List<List<Object>>  rows = rowsList.getValues();
                List<String> columns = rowsList.getColumns();
                for (List<Object> row : rows) {
                    List<Object> reasonEntity = SeriesResult.buildEntry(row,columns);
                    listEntry.add(reasonEntity);
                }
            }

        }
        log.info("buildEntryList size: {}.",listEntry.size());
        if(StringUtils.isEmpty(host)) {
            return SeriesResult.build(listEntry);
        }else{
            return SeriesResult.buildHost(listEntry,host);
        }
    }
    public static void addResult(SeriesResult result0,SeriesResult result) {
        List<List<Object>> listEntry = new ArrayList<>();
        for(List<Object> list0 : result0.getPoints()){
            long time0 = (long)list0.get(0);
            double value0 = fmtNull(list0.get(1));
            for(List<Object> list : result.getPoints()){
                long time = (long)list.get(0);
                double value = fmtNull(list.get(1));
                if(time==time0&&value!=0&&value0!=0){
                    List<Object> points = new ArrayList<>();
                    points.add(time);
                    points.add(value+value0);
                    listEntry.add(points);
                }
            }
        }
        result0.setPoints(listEntry);
    }
    private static List<Object> addObject(List<Object> obj1, List<Object> obj2, boolean flag) {

        long time0 = (long)obj1.get(0);
        double value0 = fmtNull(obj1.get(1));
        double value = fmtNull(obj2.get(1));

        List<Object> points = new ArrayList<>();
        points.add(time0);
        if(flag) {
            points.add(value0 + value);
        }else {// 做减法处理
            double diff = (value0 - value);
//            log.info("diff:{}, {}, {}.", diff, value0, value);
            points.add(diff<0 ? 0 : diff);
        }
        return points;
    }

    public static void addResult2(SeriesResult result0, SeriesResult result, boolean flag) {

        List<List<Object>> listEntry = new ArrayList<>();

        List<List<Object>> aList = result0.getPoints();
        List<List<Object>> bList = result.getPoints();

        int i=0,j=0;
        for(;i<aList.size() && j<bList.size();) {
            List<Object> a = aList.get(i);
            List<Object> b = bList.get(j);
//            if(! flag) log.info("a:{}, b:{}.", a, b);
            long time0 = (long)a.get(0);
            long time = (long)b.get(0);
            if(time0==time) {
                ++i; ++j;
                listEntry.add(addObject(a, b, flag));
            }else if(time0>time) {
                listEntry.add(b);
                ++j;
            }else {
                listEntry.add(a);
                ++i;
            }
        }
        for(;i<aList.size();++i) {
            List<Object> a = aList.get(i);
            listEntry.add(a);
        }
        for(;j<bList.size();++j) {
            List<Object> b = bList.get(j);
            listEntry.add(b);
        }
        result0.setPoints(listEntry);
    }


    public static double fmtNull(Object str){
        if(str==null || str.equals("null") || str.equals("")) {
            return 0.0;
        }
        try {
            if(str instanceof Double) {
                return (Double)str;
            }
            return Double.parseDouble((String)str);
        }catch (Exception e) {
            log.warn("str : {} {}",str,e.toString());
        }
        return 0;
    }
}
